#include "sms_base_node.h"
#include <fstream>


namespace sms {


BaseNode::BaseNode(
    std::string node_name,
    std::string job_name,
    std::string param_file,
    std::string ip,
    int port
) : std::thread(), 
    _sms_param(node_name + "_" + job_name, std::bind(&BaseNode::params_changed, this, std::placeholders::_1), ip, port),
    logger(node_name + "_" + job_name)
{
    this->_shutdown = false;
    this->_node_name = node_name;
    this->_job_name = job_name;
    this->_ip = ip;
    this->_port = port;

    if (param_file.size() > 0)
    {
        std::ifstream ifs(param_file);
        nlohmann::json json_params = nlohmann::json::parse(ifs);
        std::string n_name = "/" + node_name + "/";
        std::string r_name = "/" + node_name + "_" + job_name + "/";
        std::string g_name = "/_global/";
        for (auto it = json_params.begin(); it!= json_params.end(); ++it)
        {
            std::string key = it.key();
            auto value = it.value();
            if (_startswith(key, n_name))
            {
                std::string param_key = key.substr(n_name.size(), key.size() - n_name.size());
                this->get_param(param_key, value);
            }
            if (_startswith(key, r_name))
            {
                std::string param_key = key.substr(r_name.size(), key.size() - r_name.size());
                this->get_param(param_key, value);
            }
            if (_startswith(key, g_name))
            {
                std::string param_key = key.substr(g_name.size(), key.size() - g_name.size());
                this->_global_params[param_key] = value;
            }
        }
    }
}


BaseNode::~BaseNode()
{

}


void BaseNode::params_changed(nlohmann::json msg)
{

}

void BaseNode::start()
{
    std::thread t(&BaseNode::run, this);
    std::swap(static_cast<std::thread&>(*this), t);
}

void BaseNode::set_param(std::string param_name, nlohmann::json value)
{
    this->_sms_param.set_param(param_name, value);
}

nlohmann::json BaseNode::get_param(std::string param_name, nlohmann::json default_)
{
    return this->_sms_param.get_param(param_name, default_);
}

void BaseNode::run()
{
    while (this->is_running())
    {
        this->logger.info("Hello BaseNode!");
        sleep(1);
    }
}


void BaseNode::release()
{
    this->_sms_param.kill();
}


void BaseNode::shutdown()
{
    this->_shutdown = true;
}


bool BaseNode::is_running()
{
    return !_shutdown;
}



}
